using System;
using System.Collections.Generic;
using System.Text;

using ASPNETLibrary.SharePoint.WebParts.GeneratorEngine;

namespace ASPNETLibrary.SharePoint.WebParts.Generator
{
    class Program
    {
        private const string CommandArgSource = "source";
        private const string CommandArgTarget = "target";
        private const string CommandArgNamespace = "namespace";
        private const string CommandArgOverwrite = "overwrite";

        static void Main(string[] args)
        {
            bool processingSucceeded = false;
            bool argsValid = false;
            Dictionary<string, string> commands = ParseArgs(args, out argsValid);

            if (argsValid)
            {
                Console.WriteLine("Starting with processing..." + Environment.NewLine);
                Console.WriteLine("Source: " + commands[CommandArgSource]);
                Console.WriteLine("Target: " + commands[CommandArgTarget]);
                Console.WriteLine("Namespace: " + commands[CommandArgNamespace]);
                Console.WriteLine("Overwrite: " + commands[CommandArgOverwrite]);
                Console.WriteLine(Environment.NewLine);

                SkinnedWebPartsGenerator generator = new SkinnedWebPartsGenerator(Console.Out);

                if (generator.GenerateSkinnedWebPart(
                    commands[CommandArgSource], commands[CommandArgTarget], 
                    commands[CommandArgNamespace], bool.Parse(commands[CommandArgOverwrite])))
                {
                    processingSucceeded = true;
                    Console.WriteLine("Process completed successfully.");
                }
            }

            if(!processingSucceeded)
            {
                Console.WriteLine("Process failed.");
            }
        }

        private static Dictionary<string, string> ParseArgs(string[] args, out bool argsValid)
        {
            argsValid = true;
            Dictionary<string, string> commands = null;

            if (args == null || args.Length == 0)
            {
                argsValid = false;
            }
            else
            {
                commands = new Dictionary<string, string>();
                for(int currArgIndex = 0; currArgIndex < args.Length; currArgIndex++)
                {
                    string arg = args[currArgIndex];

                    string argName = null, argValue = null;
                    if (!(arg[0] == '/'))
                    {
                        argsValid = false;
                        Console.WriteLine("Error, invalid argument: " + arg);
                    }
                    else
                    {
                        string[] argParts = (arg.Substring(1)).Split(new char[] { ':' });
                        if (argParts != null)
                        {
                            argName = argParts[0];
                            if (argParts.Length > 1)
                            {
                                argValue = argParts[1];
                            }
                        }
                        else
                        {
                            argsValid = false;
                        }
                        if (CommandArgSource.Equals(argName.ToLower(), StringComparison.InvariantCultureIgnoreCase) ||
                            CommandArgTarget.Equals(argName.ToLower(), StringComparison.InvariantCultureIgnoreCase) ||
                            CommandArgNamespace.Equals(argName.ToLower(), StringComparison.InvariantCultureIgnoreCase) ||
                            CommandArgOverwrite.Equals(argName.ToLower(), StringComparison.InvariantCultureIgnoreCase))
                        {
                            commands.Add(argName, argValue);
                        }
                        else
                        {
                            argsValid = false;
                            Console.WriteLine("Unknown switch: " + argName);
                        }
                    }
                }
            }

            if (argsValid)
            {
                //Check if target was specified and if not then generate it based on source file name
                CheckTargetFilename(commands);

                //Check if 'overwrite' switch was set and set its value
                CheckOverwriteSwitch(commands);

                //Check if mandatory parameters are specified
                if (!ValidateMandatoryArgs(commands))
                {
                    argsValid = false;
                    ShowUsage();
                }
            }
            else
            {
                ShowUsage();
            }

            return commands;
        }

        private static bool ValidateMandatoryArgs(Dictionary<string, string> commands)
        {
            bool retVal = false;

            //All four arguments must be set before the call to this method
            if (commands.ContainsKey(CommandArgSource) && commands.ContainsKey(CommandArgTarget) &&
                commands.ContainsKey(CommandArgNamespace) && commands.ContainsKey(CommandArgOverwrite))
            {
                retVal = true;
            }
            return retVal;
        }

        private static void CheckOverwriteSwitch(Dictionary<string, string> commands)
        {
            if (commands.ContainsKey(CommandArgOverwrite))
            {
                commands[CommandArgOverwrite] = bool.TrueString;
            }
            else
            {
                commands.Add(CommandArgOverwrite, bool.FalseString);
            }
        }

        private static void CheckTargetFilename(Dictionary<string, string> commands)
        {
            if (commands.ContainsKey(CommandArgSource) &&
                !String.IsNullOrEmpty(commands[CommandArgSource]) &&
                (!commands.ContainsKey(CommandArgTarget) || (commands.ContainsKey(CommandArgTarget) && String.IsNullOrEmpty(commands[CommandArgTarget]))))
            {
                string source = commands[CommandArgSource];
                string target = null;
                int lastDotIndex = source.LastIndexOf('.');
                if (lastDotIndex > -1)
                {
                    target = source.Substring(0, lastDotIndex) + ".cs";
                }
                if (target != null)
                {
                    if (commands.ContainsKey(CommandArgTarget) && String.IsNullOrEmpty(commands[CommandArgTarget]))
                    {
                        commands[CommandArgTarget] = target;
                    }
                    else
                    {
                        commands.Add(CommandArgTarget, target);
                    }
                }
            }
        }

        private static void ShowUsage()
        {
            Console.WriteLine(
                @"

Generates skinned Web Part.

    SPWGEN /source:SOURCEFILENAME [/target:TARGETFILENAME] /namespace:NAMESPACE [/overwrite]

    /source     Specifies the skin file (ASCX) to be used as base for skinned 
                Web Part generation; SOURCEFILENAME can be a relative path to 
                skin file or an absolute path
    /target     Specifies the name of file that will be generated; TARGETFILENAME 
                can be a relative or absolute path; if 'target' switch is not 
                specified then skin's filename will be used as base for Web Part's 
                name but extension will be changed to '.cs'
    /namespace  Specifies the namespace for new skinned Web Part
    /overwrite  Specifies if target files should be overwritten if they already exist.

    Examples:
    swpgen /source:SampleWebPart.ascx /target:SampleWebPart.cs /namespace:MyCompany.MyProject.WebParts /overwrite
    swpgen /source:SampleWebPart.ascx /namespace:MyCompany.MyProject.WebParts

                ");
        }
    }
}